/*******************************************************************************
 MRF24WG register access

  Summary: Functions to access registers on MRF24WG

  Description: Same as summary
*******************************************************************************/

/* MRF24WG0M Universal Driver
*
* Copyright (c) 2012-2013, Microchip <www.microchip.com>
* Contact Microchip for the latest version.
*
* This program is free software; distributed under the terms of BSD
* license:
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1.    Redistributions of source code must retain the above copyright notice, this
*        list of conditions and the following disclaimer.
* 2.    Redistributions in binary form must reproduce the above copyright notice,
*        this list of conditions and the following disclaimer in the documentation
*        and/or other materials provided with the distribution.
* 3.    Neither the name(s) of the above-listed copyright holder(s) nor the names
*        of its contributors may be used to endorse or promote products derived
*        from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
 * Modified for port to ARC processor
 * by Huaqi Fang huaqi.fang@synopsys.com, Synopsys, Inc.
 */

//==============================================================================
//                                  INCLUDES
//==============================================================================
#include <stdlib.h>
#include "wf_dev_hal.h"

#include "./inc/shared/wf_universal_driver.h"
#include "./inc/internal/wf_global_includes.h"

//==============================================================================
//                                  LOCAL GLOBALS
//==============================================================================
// using global buffers because the register functions are called from the
// external interrupt routine, and for parts that use overlay memory using local
// buffers fails.
static uint8_t g_txBuf[3];
static uint8_t g_rxBuf[3];

static DEV_SPI_TRANSFER wf_spi_tsf_cmd;

#define WFSPI_CHECK_EXP_NORTN(EXPR)     CHECK_EXP_NOERCD(EXPR, error_exit)

/*****************************************************************************
 * FUNCTION: Read8BitWFRegister
 *
 * RETURNS: register value
 *
 * PARAMS:
 *      regId -- ID of 8-bit register being read
 *
 *  NOTES: Reads WF 8-bit register
 *****************************************************************************/
uint8_t Read8BitWFRegister(uint8_t regId)
{
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    g_txBuf[0] = regId | WF_READ_REGISTER_MASK;

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, g_txBuf, 0, 1);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, g_rxBuf, 1, 1);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

error_exit:
    return g_rxBuf[0];   /* register value returned in the second byte clocking */
}

/*****************************************************************************
 * FUNCTION: Write8BitWFRegister
 *
 * RETURNS: None
 *
 * PARAMS:
 *      regId -- ID of 8-bit register being written to
 *      value -- value to write
 *
 *  NOTES: Writes WF 8-bit register
 *****************************************************************************/
void Write8BitWFRegister(uint8_t regId, uint8_t value)
{
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    g_txBuf[0] = regId | WF_WRITE_REGISTER_MASK;
    g_txBuf[1] = value;

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, g_txBuf, 0, 2);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, g_rxBuf, 2, 0);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

error_exit:
    return;
}

/*****************************************************************************
 * FUNCTION: Write16BitWFRegister
 *
 * RETURNS: None
 *
 * PARAMS:
 *      regId -- ID of 16-bit register being written to
 *      value -- value to write
 *
 *  NOTES: Writes WF 16-bit register
 *****************************************************************************/
void Write16BitWFRegister(uint8_t regId, uint16_t value)
{
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    g_txBuf[0] = regId | WF_WRITE_REGISTER_MASK;
    g_txBuf[1] = (uint8_t)(value >> 8);       /* MS byte being written     */
    g_txBuf[2] = (uint8_t)(value & 0x00ff);   /* LS byte being written     */

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, g_txBuf, 0, 3);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, g_rxBuf, 3, 0);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

error_exit:
    return;
}

/*****************************************************************************
 * FUNCTION: Read16BitWFRegister
 *
 * RETURNS: register value
 *
 * PARAMS:
 *      regId -- ID of 16-bit register being read
 *
 *  NOTES: Reads WF 16-bit register
 *****************************************************************************/
uint16_t Read16BitWFRegister(uint8_t regId)
{
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    g_txBuf[0] = regId | WF_READ_REGISTER_MASK;

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, g_txBuf, 0, 1);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, g_rxBuf, 1, 2);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

error_exit:
    return (((uint16_t)g_rxBuf[0]) << 8) | ((uint16_t)(g_rxBuf[1]));
}

/*****************************************************************************
 * FUNCTION: WriteWFArray
 *
 * RETURNS: None
 *
 * PARAMS:
 *      regId  -- Raw register being written to
 *      pBuf   -- pointer to array of bytes being written
 *      length -- number of bytes in pBuf
 *
 *  NOTES: Writes a data block to specified raw register
 *****************************************************************************/
void WriteWFArray(uint8_t regId, const uint8_t *p_Buf, uint16_t length)
{
    uint8_t *data_buf;
    uint16_t i;
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    data_buf = malloc(length + 1);

    if (data_buf == NULL) {
        return;
    }

    data_buf[0] = regId;
    for (i = 1; i <= length ; i++) {
        data_buf[i] = *p_Buf;
        p_Buf++;
    }

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, data_buf, 0, length + 1);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, g_rxBuf, 1, 0);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

   // DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_data, p_Buf, 0, length);
   // DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_data, g_rxBuf, length, 0);
   // DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_data, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

    free(data_buf);

error_exit:
    return;
}

/*****************************************************************************
 * FUNCTION: ReadWFArray
 *
 * RETURNS: None
 *
 * PARAMS:
 *      regId  -- Raw register being read from
 *      pBuf   -- pointer where to write out bytes
 *      length -- number of bytes to read
 *
 *  NOTES: Reads a block of data from a raw register
 *****************************************************************************/
void ReadWFArray(uint8_t  regId, uint8_t *p_Buf, uint16_t length)
{
    WF_OPS *p_wf_ops = get_wf_ops();

    WFSPI_CHECK_EXP_NORTN(p_wf_ops);

    /* output command byte */
    g_txBuf[0] = regId | WF_READ_REGISTER_MASK;

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_SELECTED);

    DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_cmd, g_txBuf, 0, 1);
    DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_cmd, p_Buf, 1, length);
    DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_cmd, NULL);

    // DEV_SPI_XFER_SET_TXBUF(&wf_spi_tsf_data, p_Buf, 0, 0);
    // DEV_SPI_XFER_SET_RXBUF(&wf_spi_tsf_data, p_Buf, 0, length);
    // DEV_SPI_XFER_SET_NEXT(&wf_spi_tsf_data, NULL);

    p_wf_ops->spi_ops->spi_transfer(&wf_spi_tsf_cmd);

    p_wf_ops->spi_ops->spi_cs(WF_CHIP_DESELECTED);

error_exit:
    return;
}


